package com.gee.spring.boot.starter.opengemini.core.domain.lambda;


import com.gee.spring.boot.starter.opengemini.core.util.ExceptionUtil;
import com.gee.spring.boot.starter.opengemini.core.util.ReflectionUtil;

import java.lang.reflect.Field;

import static com.gee.spring.boot.starter.opengemini.core.constant.StrConstant.*;

/**
 * @author gepengjun
 * @since 2024/4/28 16:45
 */
public class ReflectLambdaMeta implements LambdaMeta {
    private static final Field FIELD_CAPTURING_CLASS;

    static {
        Field fieldCapturingClass;
        try {
            Class<SerializedLambda> aClass = SerializedLambda.class;
            fieldCapturingClass = ReflectionUtil.setAccessible(aClass.getDeclaredField("capturingClass"));
        } catch (Throwable e) {
            fieldCapturingClass = null;
        }
        FIELD_CAPTURING_CLASS = fieldCapturingClass;
    }

    private final SerializedLambda lambda;

    public ReflectLambdaMeta(SerializedLambda lambda) {
        this.lambda = lambda;
    }

    @Override
    public String getImplMethodName() {
        return lambda.getImplMethodName();
    }

    @Override
    public Class<?> getInstantiatedClass() {
        String instantiatedMethodType = lambda.getInstantiatedMethodType();
        String instantiatedType = instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(SEMICOLON)).replace(SLASH, DOT);
        return ReflectionUtil.toClassConfident(instantiatedType, getCapturingClassClassLoader());
    }

    private ClassLoader getCapturingClassClassLoader() {
        // 如果反射失败，使用默认的 classloader
        if (FIELD_CAPTURING_CLASS == null) {
            return null;
        }
        try {
            return ((Class<?>) FIELD_CAPTURING_CLASS.get(lambda)).getClassLoader();
        } catch (IllegalAccessException e) {
            throw ExceptionUtil.re(e);
        }
    }

}
